/******************************************************************************
* 
*****************************************************************************/

package com.gw.business.common.util.excel;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletResponse;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;


/**
 * @author  kidy
 * @since   1.0
 * @version 2015年1月23日 kidy
 */
public class  ExcelOperate<T>{
    private static Log log = LogFactory.getLog(ExcelOperate.class);// Log

    private String fileName;// 文件名

    private String[] thNames;// 表头名集合

    private String[] fields;// 属性名集合

    private List<T> dataList;// 数据集合

    private String sheetName = "sheet1";// excel sheet名称 : 默认名称sheet1

    private HSSFWorkbook hssfWorkbook;// HSSFWork

    private HSSFSheet hssfSheet;// Sheet

    private Map<String, String> thAndFieldMap;// Map : 数据存储方式 Map<属性名,表头名>

    private InputStream inputStream;// InputStream : 导出文件流

    private File file;// 文件

    private T t;// 泛型类

    public ExcelOperate() {
        super();
    }

    /**
     * @param fileName
     *            :文件名
     * @param dataList
     *            : 数据集合
     * @param sheetName
     *            : excel sheet 名
     * @param thAndFieldMap
     *            : 表头和属性名Map 存储方式 Map<属性名,表头名>
     */
    public ExcelOperate(List<T> dataList, String sheetName, String fileName,
            Map<String, String> thAndFieldMap) {
        super();
        this.dataList = dataList;
        this.fileName = fileName;
        this.sheetName = sheetName;
        this.thAndFieldMap = thAndFieldMap;
    }

    /**
     * 
     * @param dataList
     *            : 数据集合
     * @param fields
     *            : 属性名集合
     * @param fileName
     *            :文件名
     * @param sheetName
     *            : excel sheet 名
     * @param thNames
     *            : 表头名
     */
    public ExcelOperate(List<T> dataList, String[] fields, String fileName,
            String sheetName, String[] thNames) {
        super();
        this.dataList = dataList;
        this.fields = fields;
        this.fileName = fileName;
        this.sheetName = sheetName;
        this.thNames = thNames;
    }

    /**
     * excel导出文件流 ExcelOperate设置(thNames, fields, dataList, sheetName)
     * 
     * @return
     */
    public InputStream excelExport(final String fileName,
            Map<String, String> thAndFieldMap, List<T> dataList,
            final String sheetName) {
        this.dataList = dataList;
        this.fileName = fileName;
        this.sheetName = sheetName;
        this.thAndFieldMap = thAndFieldMap;
        this.fields = thAndFieldMap.keySet().toArray(new String[] {});
        this.thNames = thAndFieldMap.values().toArray(new String[] {});
        return excelExport(thNames, fields, dataList, sheetName);
    }

    /**
     * excel导出文件流 ExcelOperate设置(thNames, fields, dataList, sheetName)
     * 
     * @return
     */
    public InputStream excelExportAfterBatchAdd() {
        return excelExport(thNames, fields, dataList, sheetName);
    }

    /**
     * excel导出文件流
     * 
     * @param filename
     *            文件名
     * @param columns
     *            表头名
     * @param fields
     *            属性
     * @param list
     *            数据
     * @param sheet
     * @return
     */
    public InputStream excelExport(final String fileName,
            final String[] thNames, final String[] fields, List<T> dataList,
            final String sheetName) {
        this.fileName = fileName;
        return excelExport(thNames, fields, dataList, sheetName);
    }

    /**
     * excel导出文件流 : 批量导出
     * 
     * @param filename
     *            文件名
     * @param columns
     *            表头名
     * @param fields
     *            属性
     * @param list
     *            数据
     * @param sheet
     * @return
     */
    public InputStream excelExport(HttpServletResponse response) {
        batchAdd(thNames, fields, dataList, sheetName,response);
        return excelExport(thNames, fields, dataList, sheetName);
    }
    /**
     * 
     * FIXME 方法注释信息(此标记自动完成,注释填写完成后请删除)
     * <pre>
     * 
     * </pre>
     */
    public void excelExportTemp(OutputStream out,HttpServletResponse response) {
        batchAdd(thNames, fields, dataList, sheetName,response);
       
        try {
          //  excelExport(thNames, fields, dataList, sheetName,out);
        } catch (Exception e) {
            e.printStackTrace();
        }
       
    }
    /**
     * 直接导出 : 不需要经过batchAdd方法 excel导出文件流
     * 
     * @param columns
     *            表头名
     * @param fields
     *            属性
     * @param list
     *            数据
     * @param sheet
     * @return
     */
    public InputStream excelExport(final String[] thNames,
            final String[] fields, List<T> dataList, String sheetName) {
        this.thNames = thNames;
        this.fields = fields;
        this.dataList = dataList;
        this.sheetName = sheetName;
        try {
            ByteArrayOutputStream baos = new ByteArrayOutputStream();// 构建文件流
            hssfWorkbook.write(baos);
            inputStream = new ByteArrayInputStream(baos.toByteArray());
        } catch (Exception e) {
            log
                    .error(
                            ".excelExport(final String[] thNames,final String[] fields, List<T> dataList, String sheetName):",
                            e);
        }
        return inputStream;
    }
 
    /**
     * 批量添加数据 对象设置 thNames, fields, dataList, sheetName
     */
    public void batchAdd(HttpServletResponse response) {
        batchAdd(thNames, fields, dataList, sheetName,response);
    }

    /**
     * 批量添加数据
     * 
     * @param columns
     *            表头名
     * @param fields
     *            属性
     * @param list
     *            数据
     * @param sheet
     * @return
     */
    public void batchAdd(final String[] thNames, final String[] fields,
            List<T> dataList, String sheetName,HttpServletResponse response) {
        if (hssfWorkbook == null && hssfSheet == null) {
            hssfWorkbook = new HSSFWorkbook();// 创建一个工作间
            hssfSheet = hssfWorkbook.createSheet(sheetName);// 创建一个sheet
        }
        HSSFRow row = hssfSheet.createRow(0);// 创建第一行(存储表头名)
        HSSFCell cell = null;// 表头
        for (int cellIndex = 0; cellIndex < thNames.length; cellIndex++) {
            cell = row.createCell(cellIndex);
            cell.setCellValue(thNames[cellIndex]); // 设置表头名
        }
        if (null != dataList && dataList.size() > 0) {
            for (int rowIndex = 0; rowIndex < dataList.size(); rowIndex++) {// 数据拆分
                row = hssfSheet.createRow(rowIndex + 1);// 创建属性对象(创建+1行)
                for (int f = 0; f < fields.length; f++) {
                    T t = dataList.get(rowIndex);// 创建列
                    Object rtnV = getFieldRtnVal(t, fields[f]);
                    cell = row.createCell(f);
                    setCellValue(cell, rtnV);// 设置cell数据
                }
            }
        }
        try {
          
            hssfWorkbook.write(response.getOutputStream());
            response.getOutputStream().flush();
            response.getOutputStream().close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        
       
    }

    /**
     * 添加单行
     * 
     * @param thNames
     *            : 表头名数组
     * @param values
     *            : 值数组
     */
    public void addTr(final String[] thNames, Object... values) {
        if (hssfWorkbook == null && hssfSheet == null) {
            hssfWorkbook = new HSSFWorkbook();
            hssfSheet = hssfWorkbook.createSheet(sheetName);
        }
        int rowNum = hssfSheet.getLastRowNum() + 1;
        HSSFRow row = null;
        HSSFCell cell = null;
        row = hssfSheet.createRow(rowNum);
        for (int i = 0; i < thNames.length; i++) {
            cell = row.createCell(i);
            setCellValue(cell, thNames[i]);
        }
        // row = hssfSheet.createRow(rowNum+1);
        for (int i = thNames.length; i < 2 * thNames.length; i++) {
            cell = row.createCell(i);
            setCellValue(cell, values[i / 2]);
        }
    }

    /**
     * 由于HSSFCell.setCellValue不可设置object,必须转换为常用数据类型
     * 
     * @param cell
     * @param cellValue
     */
    protected void setCellValue(HSSFCell cell, Object cellValue) {
        if (cellValue instanceof Number) {
            cell.setCellValue(
                    Double.valueOf(cellValue.toString()));
        } else if (cellValue instanceof Boolean) {
            cell.setCellValue((Boolean) cellValue);
        } else if (cellValue instanceof Date) {
            cell.setCellValue(new SimpleDateFormat(
                    "yyyy-MM-dd HH:mm:ss").format(cellValue));
        } else {
            cell.setCellValue((String) cellValue);
        }
    }

    /**
     * 返回对象中单个属性值 : 针对 get无参方法 如果传递属性为Map..传递规则 : map.key
     * 
     * @param obj
     *            对象
     * @param field
     *            属性
     */
    @SuppressWarnings("unchecked")
    public static Object getFieldRtnVal(Object obj, String field) {
        StringBuffer method = new StringBuffer();
        method.append(ConditionCollection.PREFIX_GET);
        String f = "", mapKey = "";// 属性名区分
        if (field.indexOf(ConditionCollection.STR_POINT) != -1) {// 如果属性为map,
                                                                    // 则map表现形式
                                                                    // :"map.key"
            f = field.split(ConditionCollection.SPLIT_POINT)[0];
            mapKey = field.split(ConditionCollection.SPLIT_POINT)[1];// 取map.key
        } else {
            f = field;// 非Map属性
        }
        method.append(f.substring(0, 1).toUpperCase());
        method.append(f.substring(1));
        Object rtnObj = null;// 返回对象
        try {
            Method newMethod = obj.getClass().getMethod(method.toString(),
                    new Class[] {});// 如果使用getDeclaredMethod，只可使用该类本身声明的方法
                                    // (父类方法不包括在内)
            rtnObj = newMethod.invoke(obj, new Object[] {});
            if (rtnObj instanceof Map) {// 返回对象 : Map
                rtnObj = ((Map) rtnObj).get(mapKey);// 返回值为map.get(key)
                mapKey = null;
                f = null;
            }
            method = null;
            newMethod = null;

        } catch (Exception e) {
            log.error(".getMethodRtnVal(Object obj, String field)", e);
        }
        return rtnObj;
    }

    /**
     * 文件名称(转为ISO-8859-1编码格式后):主要是提供给下载
     * 
     * @return
     */
    public String getFileName() {
        try {
            return new String(fileName.getBytes(),
                    ConditionCollection.ENCODING_ISO_8859_1);
        } catch (UnsupportedEncodingException e) {
            return fileName;
        }
    }

    /**
     * 原始文件名称
     * 
     * @return
     */
    public String getDefaultFileName() {
        return fileName;
    }

    public void setFileName(String fileName) {
        this.fileName = fileName;
    }

    public String[] getThNames() {
        return thNames;
    }

    public void setThNames(String[] thNames) {
        this.thNames = thNames;
    }

    public String[] getFields() {
        return fields;
    }

    public void setFields(String[] fields) {
        this.fields = fields;
    }

    public List<T> getDataList() {
        return dataList;
    }

    public void setDataList(List<T> dataList) {
        this.dataList = dataList;
    }

    public String getSheetName() {
        return sheetName;
    }

    public void setSheetName(String sheetName) {
        this.sheetName = sheetName;
    }

    public HSSFWorkbook getHssfWorkbook() {
        return hssfWorkbook;
    }

    public void setHssfWorkbook(HSSFWorkbook hssfWorkbook) {
        this.hssfWorkbook = hssfWorkbook;
    }

    public HSSFSheet getHssfSheet() {
        return hssfSheet;
    }

    public void setHssfSheet(HSSFSheet hssfSheet) {
        this.hssfSheet = hssfSheet;
    }

    public Map<String, String> getThAndFieldMap() {
        return thAndFieldMap;
    }

    public void setThAndFieldMap(Map<String, String> thAndFieldMap) {
        fields = thAndFieldMap.keySet().toArray(new String[] {});
        thNames = thAndFieldMap.values().toArray(new String[] {});
        this.thAndFieldMap = thAndFieldMap;
    }

    public InputStream getInputStream() {
        return inputStream;
    }

    public File getFile() {
        return file;
    }

    public T getT() {
        return t;
    }

    public void setT(T t) {
        this.t = t;
    }

    public static void main(String[] args) {

    }
}
